/**
 * 前端版本的处方计算工具 (由后端 RxUtil Java 代码移植)
 * 功能：
 * 1. validateStorage 验证库存是否足够
 * 2. calculateTotalDose 计算总用药量（按最小单位）
 * 3. calculatePrice 计算出库价格（支持拆零或整盒）
 * 4. calculateAll 综合计算并返回更丰富拆分信息（扩展）
 */

export type YesNo = 'Y' | 'N' | boolean | undefined | null | '1' | '0';

/** 将多种 Yes/No 表达统一成布尔 */
function toBool(value: YesNo): boolean {
  if (value === true) return true;
  if (value === false) return false;
  if (value === 'Y') return true;
  if (value === 'N') return false;
  if (value === '1') return true;
  if (value === '0') return false;
  return false; // 默认按不允许处理
}

/**
 * 验证库存是否足够
 * @param minPackQty 每盒最小单位数量 (一盒多少片)
 * @param stockQty 整盒库存数量 (盒)
 * @param minStockQty 零散库存数量 (片)
 * @param totalOutQty 需要出库的总量 (片)
 */
/**
 * 验证库存是否足够（TypeScript实现）
 * @param minPackQty 最小包装数（一盒有几片）
 * @param stockQty 整盒的库存（盒数）
 * @param minStockQty 散装的库存（片数）
 * @param totalOutQty 出库量（片数或盒数，取决于isSplit）
 * @param isSplit 是否允许拆分
 * @returns {boolean} 库存是否足够
 */
export type YesOrNo = 'Y' | 'N' | boolean | undefined | null | '1' | '0';
// type YesOrNo = 'YES' | 'NO';
export function validateStorage(
  minPackQty: number,
  stockQty: number,
  minStockQty: number,
  totalOutQty: number,
  isSplit: YesOrNo
): boolean {
  const allowSplit = toBool(isSplit); // true=允许拆分
  const actualOutQty = allowSplit ? totalOutQty * minPackQty : totalOutQty;
  const totalStockQty = stockQty * minPackQty + minStockQty;
  return totalStockQty >= actualOutQty;
}

/**
 * 向上取整到指定位小数；Java 里通过 BigDecimalUtils.format，这里等价处理。
 */
function roundUp(value: number, scale: number): number {
  if (scale <= 0) return Math.ceil(value);
  const factor = Math.pow(10, scale);
  return Math.ceil(value * factor) / factor;
}

/**
 * 计算用药总量（前端实现）
 * @param {number} dosage - 每次用量（可小数，如0.33片）
 * @param {number} frequencyTimes - 每天用药次数
 * @param {number} cycle - 用药周期（天数）
 * @param {boolean} isMinSplit - 是否允许最小单位拆分
 * @param {boolean} isSplit - 是否允许拆零销售
 * @param {number} minPackQty - 每盒最小单位数量（片数）
 * @returns {number} 总用药量（片数或盒数）
 */
export function calculateTotalDose(
  dosage: number,
  frequencyTimes: number,
  cycle: number,
  isMinSplit: any,
  isSplit: any,
  minPackQty: number | undefined
) {
  let totalDose = 0;

  for (let day = 0; day < cycle; day++) {
    for (let time = 0; time < frequencyTimes; time++) {
      let actualDose = dosage;

      // 如果不允许拆分最小单位，向上取整
      const allowSplit1 = toBool(isMinSplit); // true=允许拆分
      if (!allowSplit1) {
        actualDose = Math.ceil(actualDose);
      }

      totalDose += actualDose;
    }
  }

  // 总片数向上取整
  const leftoverPieces = Math.ceil(totalDose);
  const allowSplit = toBool(isSplit); // true=允许拆分
  // 如果允许拆零销售，返回片数
  if (allowSplit) {
    return leftoverPieces;
  }
  if (minPackQty == null) {
    minPackQty = 0;
  }
  // 如果不允许拆零，计算整盒数并向上取整
  return Math.ceil(leftoverPieces / minPackQty);
}

export interface PriceResult {
  totalPrice: number; // 总价格(分)
  fullBoxes: number; // 出库整盒数
  leftoverPieces: number; // 出库零散片数（允许拆零时）
}

/**
 * 计算总价格
 * @param totalOutQty 总用药量（片数，整数）
 * @param minPackQty 每盒片数
 * @param isSplit 是否允许拆零销售 ('Y'/'N'/boolean)
 * @param price 整盒价格（分）
 * @param splitPrice 单片价格（分）
 */
/**
 * 计算药品总价格
 * @param {number} totalOutQty - 出库总量(片数或盒数，取决于isSplit)
 * @param {number} minPackQty - 每盒最小单位数量(片数)
 * @param {boolean} isSplit - 是否允许拆零销售
 * @param {number} price - 整盒价格(单位：分)
 * @param {number} splitPrice - 单片价格(单位：分)
 * @returns {number} 总价格(单位：分)
 */
export function calculatePrice(
  totalOutQty: number,
  minPackQty: number,
  isSplit: any,
  price: number,
  splitPrice: number
) {
  const allowSplit = toBool(isSplit); // true=允许拆分
  if (!allowSplit) {
    return {
      totalPrice: totalOutQty * price,
      fullBoxes: totalOutQty,
      leftoverPieces: 0,
      pricePerUnit: price / minPackQty, // 等效每片价格
      isSplit: false,
    };
  }

  const fullBoxes = Math.floor(totalOutQty / minPackQty);
  const leftoverPieces = totalOutQty % minPackQty;
  const totalPrice = fullBoxes * price + leftoverPieces * splitPrice;

  return {
    totalPrice,
    fullBoxes,
    leftoverPieces,
    pricePerUnit: totalPrice / totalOutQty, // 实际每片均价
    isSplit: true,
  };
}

export interface RxAllResult extends PriceResult {
  totalDose: number; // 计算出的总出库片数
}

/**
 * 综合计算：给前端一站式结果
 */
export function calculateAll(params: {
  totalOutQty: number; // 总用药量（片数，整数）
  dosage: number; // 每次剂量（片，可小数）
  frequencyTimes: number; // 每天次数
  cycle: number; // 周期(天)
  isMinSplit: YesNo; // 是否允许拆分最小单位
  minPackQty: number; // 每盒片数
  isSplit: YesNo; // 是否允许拆零
  price: number; // 盒价(分)
  splitPrice: number; // 单片价(分)
}): RxAllResult {
  const totalDose = calculateTotalDose(
    params.dosage,
    params.frequencyTimes,
    params.cycle,
    params.isMinSplit,
    params.isSplit,
    params.minPackQty
  );
  const priceRes = calculatePrice(
    params.totalOutQty,
    params.minPackQty,
    params.isSplit,
    params.price,
    params.splitPrice
  );
  return { totalDose, ...priceRes };
}

/**
 * 示例 (不会自动执行)：
 *
 * const result = calculateAll({
 *   dosage: 0.33,
 *   frequencyTimes: 3,
 *   cycle: 15,
 *   isMinSplit: 'N', // 不允许拆分 -> 单次剂量向上取整
 *   minPackQty: 12,
 *   isSplit: 'Y', // 允许拆零销售
 *   price: 3000, // 30元 (分)
 *   splitPrice: 250 // 2.5元 (分)
 * });
 * //console.log(result);
 */

export default {
  validateStorage,
  calculateTotalDose,
  calculatePrice,
  calculateAll,
};
